﻿namespace Digitalmes.Application.Common.Models;

/// <summary>
/// API 接口返回结果。
/// </summary>
public sealed class ApiResult<TObject> : IApiResult<TObject>
{
    private const int SuccessCode = 200;

    public int Code { get; init; }

    public bool Success => Code == SuccessCode;

    [NotNull]
    public string? Message { get; init; }

    public TObject? Data { get; init; }
}

/// <summary>
/// API 接口返回结果。
/// </summary>
public sealed class ApiResult : IApiResult
{
    private const int SuccessCode = 200;

    public int Code { get; init; }

    public bool Success => Code == SuccessCode;

    [NotNull]
    public string? Message { get; init; }

    public object? Data { get; init; }

    #region 工厂对象

    /// <summary>
    /// 返回成功结果。
    /// </summary>
    /// <returns></returns>
    public static IApiResult Ok()
    {
        return new ApiResult()
        {
            Code = SuccessCode,
            Message = string.Empty,
        };
    }

    /// <summary>
    /// 返回成功结果。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="data">数据</param>
    /// <param name="message">消息</param>
    /// <returns></returns>
    public static IApiResult Ok<T>(T? data, string? message = null)
    {
        return new ApiResult()
        {
            Code = SuccessCode,
            Message = message ?? string.Empty,
            Data = data,
        };
    }

    /// <summary>
    /// 返回失败结果。
    /// </summary>
    /// <param name="message">错误原因</param>
    /// <returns></returns>
    public static IApiResult Bad(string? message = null)
    {
        return new ApiResult()
        {
            Code = 0,
            Message = message ?? string.Empty,
        };
    }

    /// <summary>
    /// 从 <see cref="IResult{T}"/> 中解析数据。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="result"><see cref="IResult{T}"/> 结果。</param>
    /// <returns></returns>
    public static IApiResult FromResult<T>(IResult<T> result)
    {
        // bool和枚举类型值会影响对应的状态码。
        int code = result.Value switch
        {
            bool ok => ok ? SuccessCode : 0,
            Enum @enum => Convert.ToInt32(@enum), // int32 枚举类型
            _ => SuccessCode,
        };

        return new ApiResult()
        {
            Code = code,
            Message = result.Message ?? string.Empty,
            Data = result.Value,
        };
    }

    /// <summary>
    /// 生成 Success 结果数据。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="data">数据</param>
    /// <param name="message">消息</param>
    /// <returns></returns>
    public static IApiResult<T> From<T>(T? data, string? message = null)
    {
        return new ApiResult<T>()
        {
            Code = SuccessCode,
            Message = message ?? string.Empty,
            Data = data,
        };
    }

    #endregion
}
